﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;

namespace HYRElectric.WirePlace
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	public class CmdCreateAllConduitByWire : YJKCommandAuto
	{
		protected override Result YJKExcute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			UIDocument activeUIDocument = cmdData.Application.ActiveUIDocument;
			this.doc = activeUIDocument.ActiveView.Document;
			this.choices = activeUIDocument.Selection;
			if (this.GetWireByProject(this.doc).Count <= 0)
			{
				MessageBox.Show("当前项目不具备生成线管的条件，请先进行设备连线。", "盈建科提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			this.DeleteExistConduit();
			using (this.dlgcreate = new DlgCreateConduitByWire(this.doc))
			{
                if (this.dlgcreate.ResultDlg == Result.Failed)
				{
					return Autodesk.Revit.UI.Result.Failed;
				}
				DialogResult dialogResult = this.dlgcreate.ShowDialog();
				if (dialogResult == DialogResult.Cancel)
				{
					return Autodesk.Revit.UI.Result.Cancelled;
				}
				if (dialogResult == DialogResult.OK)
				{
					this.conduitType = (this.dlgcreate.cbxConduitType.SelectedItem as ConduitType);
					double num = AssistFunc.mmToFeet(Convert.ToDouble(this.dlgcreate.txtHeight.Text));
					FamilySymbol symbo = this.dlgcreate.cbxElbowFittingType.SelectedItem as FamilySymbol;
					Category category = this.doc.Settings.Categories.get_Item(BuiltInCategory.OST_Conduit);
					this.doc.ActiveView.SetYJKVisibility(category, true);
					foreach (Element element in this.GetViewPlan(this.doc))
					{
						ViewPlan viewPlan = element as ViewPlan;
						if (!viewPlan.IsTemplate)
						{
							Level genLevel = viewPlan.GenLevel;
							this.height = genLevel.Elevation + num;
							ICollection<Element> wireByViewPlan = this.GetWireByViewPlan(this.doc, viewPlan);
							if (wireByViewPlan.Count > 0)
							{
								List<ElementId> list = new List<ElementId>();
								foreach (Element element2 in wireByViewPlan)
								{
									list.Add(element2.Id);
								}
								for (int i = 0; i < list.Count - 1; i++)
								{
									for (int j = 0; j < list.Count - 1 - i; j++)
									{
										if (list[j] > list[j + 1])
										{
											ElementId value = list[j];
											list[j] = list[j + 1];
											list[j + 1] = value;
										}
									}
								}
								foreach (ElementId elementId in list)
								{
									Wire wire = this.doc.GetElementById(elementId) as Wire;
									LocationCurve locationCurve = wire.Location as LocationCurve;
									XYZ hyendPoint = locationCurve.Curve.GetEndPoint(0);
									XYZ hyendPoint2 = locationCurve.Curve.GetEndPoint(1);
									Connector equConn = null;
									Connector equConn2 = null;
									ConnectorSet unusedConnectors = wire.ConnectorManager.UnusedConnectors;
									if (unusedConnectors == null || unusedConnectors.IsEmpty)
									{
										List<Connector> equipmentConnector = this.GetEquipmentConnector(wire);
										if (equipmentConnector != null && equipmentConnector.Count<Connector>() <= 0)
										{
											continue;
										}
										foreach (Connector connector in equipmentConnector)
										{
											if (connector.Domain == (Autodesk.Revit.DB.Domain)2)
											{
												if (Math.Abs(connector.Origin.X - hyendPoint.X) < this.js && Math.Abs(connector.Origin.Y - hyendPoint.Y) < this.js)
												{
													equConn = connector;
												}
												else
												{
													equConn2 = connector;
												}
											}
										}
										Conduit conduit = Conduit.Create(this.doc, this.conduitType.Id, new XYZ(hyendPoint.X, hyendPoint.Y, this.height), new XYZ(hyendPoint2.X, hyendPoint2.Y, this.height), genLevel.Id);
										List<Connector> conduitConnectors = this.GetConduitConnectors(conduit, new XYZ(hyendPoint.X, hyendPoint.Y, this.height));
										LocationCurve locationCurve2 = conduit.Location as LocationCurve;
										XYZ hyendPoint3 = locationCurve2.Curve.GetEndPoint(0);
										XYZ hyendPoint4 = locationCurve2.Curve.GetEndPoint(1);
										this.SetConduitSharePara(conduit, wire);
										SubTransaction subTransaction = new SubTransaction(this.doc);
										subTransaction.Start();
										try
										{
											this.CreateBothEndsConduit(equConn, conduitConnectors[0], hyendPoint3, wire, genLevel, symbo);
											this.CreateBothEndsConduit(equConn2, conduitConnectors[1], hyendPoint4, wire, genLevel, symbo);
											subTransaction.Commit();
											continue;
										}
										catch (Exception)
										{
											subTransaction.RollBack();
											continue;
										}
									}
									if (unusedConnectors.Size == 2)
									{
										Conduit.Create(this.doc, this.conduitType.Id, new XYZ(hyendPoint.X, hyendPoint.Y, this.height), new XYZ(hyendPoint2.X, hyendPoint2.Y, this.height), genLevel.Id);
									}
									else if (unusedConnectors.Size == 1)
									{
										Conduit conduit2 = Conduit.Create(this.doc, this.conduitType.Id, new XYZ(hyendPoint.X, hyendPoint.Y, this.height), new XYZ(hyendPoint2.X, hyendPoint2.Y, this.height), genLevel.Id);
										List<Connector> conduitConnectors2 = this.GetConduitConnectors(conduit2, new XYZ(hyendPoint.X, hyendPoint.Y, this.height));
										LocationCurve locationCurve3 = conduit2.Location as LocationCurve;
										XYZ hyendPoint5 = locationCurve3.Curve.GetEndPoint(0);
										XYZ hyendPoint6 = locationCurve3.Curve.GetEndPoint(1);
										this.SetConduitSharePara(conduit2, wire);
										List<Connector> equipmentConnector2 = this.GetEquipmentConnector(wire);
										XYZ xyz;
										Connector conduitConnector;
										if (equipmentConnector2[0].Origin.IsAlmostEqualTo(new XYZ(hyendPoint5.X, hyendPoint5.Y, equipmentConnector2[0].Origin.Z)))
										{
											xyz = hyendPoint5;
											conduitConnector = conduitConnectors2[0];
										}
										else
										{
											xyz = hyendPoint6;
											conduitConnector = conduitConnectors2[1];
										}
										if (Math.Abs(equipmentConnector2[0].Origin.Z - xyz.Z) >= this.js)
										{
											SubTransaction subTransaction2 = new SubTransaction(this.doc);
											subTransaction2.Start();
											try
											{
												this.CreateBothEndsConduit(equipmentConnector2[0], conduitConnector, xyz, wire, genLevel, symbo);
												subTransaction2.Commit();
											}
											catch (Exception)
											{
												subTransaction2.RollBack();
											}
										}
									}
								}
							}
						}
					}
				}
			}
			MessageBox.Show("批量生成线管成功！", "盈建科提示");
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void DeleteExistConduit()
		{
			foreach (Element element in new FilteredElementCollector(this.doc).OfClass(typeof(Conduit)).ToElements())
			{
				this.doc.Delete(element.Id);
			}
			foreach (Element element2 in new FilteredElementCollector(this.doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_ConduitFitting).ToElements())
			{
				this.doc.Delete(element2.Id);
			}
			this.doc.Regenerate();
		}

		private void CreateBothEndsConduit(Connector equConn, Connector conduitConnector, XYZ point, Wire wire, Level level, FamilySymbol symbo)
		{
			Conduit conduit = Conduit.Create(this.doc, this.conduitType.Id, point, equConn.Origin, level.Id);
			List<Connector> conduitConnectors = this.GetConduitConnectors(conduit, point);
			FamilyInstance familyInstance = this.doc.Create.NewElbowFitting(conduitConnectors[0], conduitConnector);
			if (this.dlgcreate.ClickEx == 1)
			{
				familyInstance.Symbol = symbo;
			}
			this.SetConduitSharePara(conduit, wire);
		}

		public ICollection<Element> GetViewPlan(Document doc)
		{
			return new FilteredElementCollector(doc).OfClass(typeof(ViewPlan)).ToElements();
		}

		public ICollection<Element> GetWireByViewPlan(Document doc, ViewPlan v)
		{
			return new FilteredElementCollector(doc, v.Id).OfClass(typeof(Wire)).OfCategory(BuiltInCategory.OST_Wire).ToElements();
		}

		public ICollection<Element> GetWireByProject(Document doc)
		{
			return new FilteredElementCollector(doc).OfClass(typeof(Wire)).OfCategory(BuiltInCategory.OST_Wire).ToElements();
		}

		private List<Connector> GetConduitConnectors(Conduit conduit, XYZ point)
		{
			ConnectorSetIterator connectorSetIterator = conduit.ConnectorManager.Connectors.ForwardIterator();
			List<Connector> list = new List<Connector>();
			Connector item = null;
			Connector item2 = null;
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector item3 = obj as Connector;
				list.Add(item3);
			}
			foreach (Connector connector in list)
			{
				if (connector.Origin.IsAlmostEqualTo(point))
				{
					item = connector;
				}
				else
				{
					item2 = connector;
				}
			}
			list.Clear();
			list.Add(item);
			list.Add(item2);
			return list;
		}

		private void SetConduitSharePara(Conduit c, Wire wire)
		{
			Dictionary<string, ParameterType> dictionary = new Dictionary<string, ParameterType>();
            dictionary.Add("材质", (ParameterType)1);
            dictionary.Add("管径", (ParameterType)143);
            dictionary.Add("所含导线", (ParameterType)1);
			foreach (KeyValuePair<string, ParameterType> keyValuePair in dictionary)
			{
				if (c.GetParameter(keyValuePair.Key) == null)
				{
					YArchitech.Revit.Electric.Common.SharedParameter.InsertSharedParameter(this.doc, BuiltInCategory.OST_Conduit, "电气数据", dictionary, true);
					break;
				}
			}
			string text = this.dlgcreate.cbxConduitMaterial.SelectedItem.ToString();
			c.GetParameter("材质").Set(text);
			string value = this.dlgcreate.cbxConduitDiameter.SelectedItem.ToString();
			c.GetParameter("管径").Set(AssistFunc.mmToFeet(Convert.ToDouble(value)));
			c.GetParameter("所含导线").Set(wire.Id.ToString());
		}

		private List<Connector> GetEquipmentConnector(Wire wire)
		{
			this.equipmentConnSet.Clear();
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = wire.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector item = obj as Connector;
				list.Add(item);
			}
			List<Element> list2 = new List<Element>();
			foreach (Connector connector in list)
			{
				ConnectorSet allRefs = connector.AllRefs;
				if (allRefs.Size > 0)
				{
					foreach (object obj2 in allRefs)
					{
						Element owner = ((Connector)obj2).Owner;
						if (owner is FamilyInstance && !list2.Contains(owner))
						{
							list2.Add(owner);
						}
					}
				}
			}
			foreach (Element element in list2)
			{
				ConnectorSetIterator connectorSetIterator2 = (element as FamilyInstance).MEPModel.ConnectorManager.Connectors.ForwardIterator();
				while (connectorSetIterator2.MoveNext())
				{
					object obj3 = connectorSetIterator2.Current;
					Connector connector2 = obj3 as Connector;
					if (connector2.Domain == (Autodesk.Revit.DB.Domain)2)
					{
						this.equipmentConnSet.Add(connector2);
					}
				}
			}
			return this.equipmentConnSet;
		}

		private ConduitType conduitType;

		private double height;

		private Selection choices;

		private Document doc;

		private double js = 0.01;

		private DlgCreateConduitByWire dlgcreate;

		private List<Connector> equipmentConnSet = new List<Connector>();
	}
}
